Strict

Rem
bbdoc: CSG
EndRem
Module Csg.Csg

ModuleInfo "Description:CSG Module based of CSG B3d code written by Warner."
ModuleInfo "Version: 0.5"
ModuleInfo "Author: Warner, LeonDrake" 
ModuleInfo "License: Free for commercial and non-commercial use" 
ModuleInfo "Copyright: none?" 

Import BRL.LinkedList
Import BRL.Retro


Const CSG_CARVE = 0
Const CSG_FILL = 1

Type CSGTriangle
	'mesh ref.
	Field mesh
	Field surf
	'vertex coords
	Field v0 : CSGVect = New CSGVect
	Field v1 : CSGVect = New CSGVect
	Field v2 : CSGVect = New CSGVect
	'plane normal/d
	Field n : CSGVect = New CSGVect
	Field on : CSGVect = New CSGVect
	Field d#
	'flags
	Field loop
End Type



Type CSGVect

	Field x#,y#,z#
	Field u#,v#

End Type



Function dist#(v1:CSGVect,v2:CSGVect)

	Local v3 : CSGVect = New CSGVect

	v3.x=v2.x-v1.x
	v3.y=v2.y-v1.y
	v3.z=v2.z-v1.z
	Return Sqr(v3.x*v3.x+v3.y*v3.y+v3.z*v3.z)

End Function

Function PointDistanceToLine#( a : CSGVect, b : CSGVect, p : CSGVect )
'| Calculates the shortest distance between a point P(xyz) And a line segment defined by A(xyz) And B(xyz) - danny.

	'get the length of each side of the triangle ABP
	ab# = Sqr( (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y) + (b.z-a.z)*(b.z-a.z) )
	bp# = Sqr( (p.x-b.x)*(p.x-b.x) + (p.y-b.y)*(p.y-b.y) + (p.z-b.z)*(p.z-b.z) )
	pa# = Sqr( (a.x-p.x)*(a.x-p.x) + (a.y-p.y)*(a.y-p.y) + (a.z-p.z)*(a.z-p.z) )

	'get the triangle's semiperimeter
	semi# = (ab+bp+pa) / 2.0
	
	'get the triangle's area
	area# = Sqr( semi * (semi-ab) * (semi-bp) * (semi-pa) )
	
	'Return closest distance P To AB
	Return (2.0 * (area/ab))
	
End Function


Function CalculateNormal:CSGVect(v0:CSGVect,v1:CSGVect,v2:CSGVect)

	Local a:CSGVect = New CSGVect
	Local b:CSGVect = New CSGVect
	Local N:CSGVect = New CSGVect
	
	'calculate normal
	a.x# = v1.x - v0.x
	a.y# = v1.y - v0.y
	a.z# = v1.z - v0.z
	b.x# = v2.x - v1.x
	b.y# = v2.y - v1.y
	b.z# = v2.z - v1.z
	N.x# = ( a.y * b.z ) - ( a.z * b.y )
	N.y# = ( a.z * b.x ) - ( a.x * b.z )
	N.z# = ( a.x * b.y ) - ( a.y * b.x )
	
	
	Return N	
	

	


End Function

Function MakeTriangle : CSGTriangle(mesh, surf, v0 : CSGVect, v1 : CSGVect, v2 : CSGVect, loop, org:CSGTriangle, n : CSGVect, d# = 0.0 )

	'distance between corners
	Local d1# = dist(v0, v1)
	Local d2# = dist(v1, v2)
	Local d3# = dist(v2, v0)
			
	'size of triangle
	opp# = PointDistanceToLine#	(x0,y0,z0,x1,y1,z1,x2,y2,z2)
	
	'remove empty triangles
	ep# = 0.01
	If ((opp < ep) Or (d1<ep) Or (d2<ep) Or (d3<ep)) Then Return

	t:CSGTriangle = New CSGTriangle

	'store mesh/surf pointer	
	t.mesh = mesh
	t.surf = surf

	'store coords		
	t.v0 = v0
	t.v1 = v1
	t.v2 = v2
		
	t.loop = loop

	'calculate normal
	ax# = x1 - x0
	ay# = y1 - y0
	az# = z1 - z0
	bx# = x2 - x1
	by# = y2 - y1
	bz# = z2 - z1
	Nx# = ( ay * bz ) - ( az * by )
	Ny# = ( az * bx ) - ( ax * bz )
	Nz# = ( ax * by ) - ( ay * bx )
	Local N : CSGVect = CalculateNormal(v0:CSGVect,v1:CSGVect,v2:CSGVect)
	Ns# = Sqr( Nx*Nx + Ny*Ny + Nz*Nz )
	If Ns > 0 Then
		Nx = Nx / Ns
		Ny = Ny / Ns
		Nz = Nz / Ns
	End If
	
	If org <> Null Then
		t\onx = org\onx
		t\ony = org\ony
		t\onz = org\onz
'		t\d  = org\d
	Else
		t\onx = nx
		t\ony = ny
		t\onz = nz
	End If
		t\nx = nx
		t\ny = ny
		t\nz = nz
		t\d = d
		
	t\d# = -((t\nx * x0) + (t\ny * y0) + (t\nz * z0))
		
	Return t

End Function